const {
  array2arrayBuffer, log, getSeqNum,
  utf8arrayFixedLength, string2utf8array,
  getNTPtime, json2string, toast, ab2hex, jump, getPageInstance, timeFormat, getCubeName, cubeIsOnline, setCubeInfo, whenOfflineSaveInfo
} = require('./util');

const _ = require('./underscore');

let time = new Date().getTime();
let count0 = 0, count1 = 0, count2 = 0, count3 = 0;

module.exports = {
  serviceId: 'E4D79BDF-4956-4B7C-9C4F-FBF6725D6166',//service id
  //bindPassword中的0x00是序号，0x30是命令
  //todo 最后1个字节变成f5，旧值8a
  bindPassword: [0xd4, 0xac, 0x25, 0xb6, 0x01, 0xb1, 0xc2, 0xb6, 0x18, 0x4a, 0xe5, 0xdd, 0x47, 0x5a, 0xbd, 0xf5],//Mobile send bind request to Cube
  cubeSendUuidNotify: 'BAE71C93-B6FE-47F7-8ED8-637C851034D8',//cube send characteristic value
  cubeReceiveUuidWrite: 'CD639E85-1F6B-4805-BA84-D2F81416B23E',//cube receive characteristic value

  writeBLECharacteristicValue: ({
                                  deviceId = '', value = [], success = () => {
    }, fail = () => {
    }, complete = () => {
    }
                                }) => {

    if (deviceId) {
      log(`writeBLECharacteristicValue:${json2string(value)}`);
      const {serviceId, cubeReceiveUuidWrite} = module.exports;
      wx.writeBLECharacteristicValue({
        //mobile->cube
        deviceId,
        serviceId,
        characteristicId: cubeReceiveUuidWrite,
        value: array2arrayBuffer(value),
        success: function (res) {
          success(json2string(res));
        },
        fail: function (res) {
          fail(json2string(res));
        },
        complete: function () {
          complete();
        }
      })
    }

  },

  reply: ({command, seqNum, deviceId}) => {

    //mobile对cube的响应。若不响应，连接将断开。
    const commandsNeedReply = [0, 1, 2, 3, 4, 5];
    const replyCommand = command + 128;
    let value = [seqNum, replyCommand];
    if (1 === command) {
      //Cube Query Time From Mobile
      const NTPtime = getNTPtime();
      value = value.concat(NTPtime);
      log(`NTPtime:${JSON.stringify(NTPtime)}`);
      log(`value include NTPtime:${JSON.stringify(value)}`);
    } else if (commandsNeedReply.indexOf(command) !== -1) {
      value.push(0);
    } else {
      return;
    }

    module.exports.writeBLECharacteristicValue({
      deviceId, value, success: () => {
        log(`writeBLECharacteristicValue success, command is:${command}`);
        console.log('成功回复了cube');
      }, fail: function (res) {
        log(`writeBLECharacteristicValue fail, command is:${command}, reason is:${'string' === typeof res ? res : JSON.stringify(res)}`);
        console.log(`失败回复了cube，原因是${json2string(res)}`);
      }
    });
  },

  parseRes: res => {
    let obj = {
      seqNum: parseInt(res.substring(0, 2), 16),
      command: parseInt(res.substring(2, 4), 16)
    };
    const {command} = obj;
    switch (command) {
      case 5:
        //Cube Upload Battery Information to Mobile
        obj.battery = parseInt(res.substring(4, 6), 16);
        obj.isCharging = parseInt(res.substring(6, 8), 16);
        break;
      case 2:
      case 3:
        //Cube uploads unstable sensor real time data to mobile
        let timeStamp = res.substring(4, 12);
        timeStamp = timeStamp.substring(6, 8) + timeStamp.substring(4, 6) + timeStamp.substring(2, 4) + timeStamp.substring(0, 2);
        obj.timeStamp = parseInt(timeStamp, 16);
        obj.pm25 = parseInt(res.substring(14, 16) + res.substring(12, 14), 16);
        const hcho = res.substring(26, 28) + res.substring(24, 26);
        if (hcho.toLowerCase() === 'ffff') {
          //cube重启后会出现ffff
          obj.hcho = '0.00';
          // obj.hcho = (parseInt(hcho, 16) / 1000).toFixed(2);;
        } else {
          obj.hcho = (parseInt(hcho, 16) / 1000).toFixed(2);
          // if(obj.hcho-0===0){
          //   obj.hcho = '0.00';
          // }
        }
        obj.battery = parseInt(res.substring(28, 30), 16);
        obj.isCharging = parseInt(res.substring(30, 32), 16);
        log(`parseRes:${res}`);
        break;
      case 0xb4:
        obj.status = parseInt(res.substring(4, 6), 16);
        break;
      default:
        obj.status = parseInt(res.substring(4, res.length), 16);
        break;

    }

    return obj;
  },
  sendPassword: function ({
                            deviceId, success = () => {
    }, fail = () => {
    }
                          }) {
    const {writeBLECharacteristicValue, bindPassword} = module.exports;
    setTimeout(() => {
      //安卓平台上，在调用notify成功后立即调用write接口，
      // 在部分机型上（比如我的华为麦芒4）会发生 10008 系统错误
      //所以设置定时器
      console.log(`发送密码开始${new Date().toString()}`);
      writeBLECharacteristicValue({
        deviceId,
        value: [getSeqNum(), 0x30].concat(bindPassword),
        success: () => {
          log('writeBLECharacteristicValue password success');
          console.log(`发送密码成功${new Date().toString()}`);
          success();
        },
        fail: function (res) {
          console.log(`发送密码失败：${new Date().toString()}，原因是${json2string(res)}`);
          fail();
        }
      });
    }, 200);
  },

  bluetoothAdapterState: function ({
                                     success = () => {
                                     }, fail = () => {
    }, jumpFlag = true, onChange = () => {
    }
                                   }) {

    wx.getBluetoothAdapterState({//需要先调用wx.openBluetoothAdapter成功后，才可使用wx.getBluetoothAdapterState
      success: function (res) {
        const {discovering, available} = res;
        if (!available) {
          fail();
        } else {
          success();
        }
      },
      fail: function (res) {
        fail();
      }
    });

  },

  discovery: function (success = () => {
  }, fail = () => {
  }) {
    const {serviceId} = module.exports;
    wx.stopBluetoothDevicesDiscovery({
      //解决android第N>1次startBluetoothDevicesDiscovery报错10008
      complete: function () {
        wx.startBluetoothDevicesDiscovery({
          /*无法搜索到正处于已连接状态的设备*/
          //开始搜寻附近的蓝牙外围设备。注意，该操作比较耗费系统资源，请在搜索并连接到设备后调用 stop 方法停止搜索。
          services: [serviceId],
          allowDuplicatesKey: true,//true...important
          interval: 0,
          success: function (res) {
            log('startBluetoothDevicesDiscovery success');
            // 监听寻找到新设备的事件
            wx.onBluetoothDeviceFound(function (devices)/*新搜索到的设备列表*/ {
              // devices&&devices.devices&&devices.devices[0]&&devices.devices[0].advertisData&&log(`#@#  ${ab2hex(devices.devices[0].advertisData)}`);
              success(devices);
            })
          },
          fail: function (res) {
            log(`startBluetoothDevicesDiscovery fail:${json2string(res)}`);
            fail();
          }
        });
      }
    })

  },
  connect: _.debounce(function ({
                                       deviceId,
                                       connectSuccess = () => {
                                       },
                                       fail = () => {
                                       },
                                       complete = () => {
                                       }
                                     }) {
    const {serviceId, cubeSendUuidNotify, sendPassword, closeBLEConnection} = module.exports;
    console.log(`createBLEConnection创建连接开始`);
    wx.createBLEConnection({
      deviceId,
      success: function (res) {

        console.log(`createBLEConnection创建连接成功`);

        console.log(`getBLEDeviceServices开始:${new Date().toString()}`);
        wx.getBLEDeviceServices({
          deviceId,
          success: function (res) {
            console.log(`getBLEDeviceServices成功:${new Date().toString()}`);

            console.log(`getBLEDeviceCharacteristics开始:${new Date().toString()}`);

            wx.getBLEDeviceCharacteristics({
              deviceId, serviceId, success: function (res) {
                console.log(`getBLEDeviceCharacteristics成功:${new Date().toString()}`);

                console.log(`notifyBLECharacteristicValueChanged开始:${new Date().toString()}`);

                wx.notifyBLECharacteristicValueChanged({
                  //cube->mobile
                  deviceId, serviceId, characteristicId: cubeSendUuidNotify, state: true,
                  success: function (res) {
                    console.log(`notifyBLECharacteristicValueChanged成功:${new Date().toString()}`);
                    sendPassword({
                      deviceId, success: function () {
                        connectSuccess({deviceId});
                      }
                    });
                  },
                  fail: function (res) {
                    fail();
                    console.log(`notifyBLECharacteristicValueChanged失败：${new Date().toString()},原因是${json2string(res)}`);
                  }
                });

              }, fail: function (res) {
                fail();
                console.log(`getBLEDeviceCharacteristics失败：${new Date().toString()}，原因是:${json2string(res)}`);
              }
            })

          },
          fail: function (res) {
            fail();
            console.log(`getBLEDeviceServices失败：${new Date().toString()}，原因是:${json2string(res)}`);
          }
        });


      },
      fail: function (res) {
        console.log(`createBLEConnection创建连接失败：${new Date().toString()}，原因是:${json2string(res)}`);
        fail();
      },
      complete: function () {
        complete();
      }
    });
  }, 2000),
  // connect: function ({
  //                      deviceId,
  //                      connectSuccess = () => {
  //                      },
  //                      fail = () => {
  //                      },
  //                      complete = () => {
  //                      }
  //                    }) {
  //
  //   const {connect_true} = module.exports;
  //   connect_true({deviceId,connectSuccess,fail,complete});
  // },
  // connect: function ({
  //                      deviceId,
  //                      connectSuccess = () => {
  //                      },
  //                      fail = () => {
  //                      },
  //                      complete = () => {
  //                      }
  //                    }) {
  //   const {serviceId, cubeSendUuidNotify, sendPassword,closeBLEConnection} = module.exports;
  //   console.log(`createBLEConnection创建连接开始`);
  //   wx.createBLEConnection({
  //     deviceId,
  //     success: function (res) {
  //
  //       console.log(`createBLEConnection创建连接成功`);
  //
  //       console.log(`getBLEDeviceServices开始:${new Date().toString()}`);
  //       wx.getBLEDeviceServices({
  //         deviceId,
  //         success: function (res) {
  //           console.log(`getBLEDeviceServices成功:${new Date().toString()}`);
  //
  //           console.log(`getBLEDeviceCharacteristics开始:${new Date().toString()}`);
  //
  //           wx.getBLEDeviceCharacteristics({
  //             deviceId, serviceId, success: function (res) {
  //               console.log(`getBLEDeviceCharacteristics成功:${new Date().toString()}`);
  //
  //               console.log(`notifyBLECharacteristicValueChanged开始:${new Date().toString()}`);
  //
  //               wx.notifyBLECharacteristicValueChanged({
  //                 //cube->mobile
  //                 deviceId, serviceId, characteristicId: cubeSendUuidNotify, state: true,
  //                 success: function (res) {
  //                   console.log(`notifyBLECharacteristicValueChanged成功:${new Date().toString()}`);
  //                   sendPassword({deviceId,success:function () {
  //                       connectSuccess({deviceId});
  //                     }});
  //                 },
  //                 fail: function (res) {
  //                   fail();
  //                   console.log(`notifyBLECharacteristicValueChanged失败：${new Date().toString()},原因是${json2string(res)}`);
  //                 }
  //               });
  //
  //             }, fail: function (res) {
  //               fail();
  //               console.log(`getBLEDeviceCharacteristics失败：${new Date().toString()}，原因是:${json2string(res)}`);
  //             }
  //           })
  //
  //         },
  //         fail: function (res) {
  //           fail();
  //           console.log(`getBLEDeviceServices失败：${new Date().toString()}，原因是:${json2string(res)}`);
  //         }
  //       });
  //
  //
  //     },
  //     fail: function (res) {
  //       console.log(`createBLEConnection创建连接失败：${new Date().toString()}，原因是:${json2string(res)}`);
  //       fail();
  //     },
  //     complete: function () {
  //       complete();
  //     }
  //   });
  //
  // },

  connect_hack: function ({
                            deviceId,
                            connectSuccess = () => {
                            },
                            fail = () => {
                            },
                            complete = () => {
                            }
                          }) {
    const {serviceId, cubeSendUuidNotify, sendPassword, closeBLEConnection} = module.exports;
    console.log(`createBLEConnection创建连接开始`);
    count0++;
    wx.createBLEConnection({
      deviceId,
      success: function (res) {

        count0--;
        console.log(`createBLEConnection创建连接成功`);


        console.log(`count0=${count0}`);

        count1++;
        console.log(`getBLEDeviceServices开始:${new Date().toString()}`);
        console.log(`count1=${count1}`);
        if (0 === count0) {
          wx.getBLEDeviceServices({
            deviceId,
            success: function (res) {
              console.log(`getBLEDeviceServices成功:${new Date().toString()}`);

              count1--;
              console.log(`getBLEDeviceCharacteristics开始:${new Date().toString()}`);

              if (0 === count1) {
                count2++;
                wx.getBLEDeviceCharacteristics({
                  deviceId, serviceId, success: function (res) {
                    console.log(`getBLEDeviceCharacteristics成功:${new Date().toString()}`);

                    count2--;
                    console.log(`notifyBLECharacteristicValueChanged开始:${new Date().toString()}`);

                    if (0 === count2) {
                      count3++;
                      wx.notifyBLECharacteristicValueChanged({
                        //cube->mobile
                        deviceId, serviceId, characteristicId: cubeSendUuidNotify, state: true,
                        success: function (res) {
                          console.log(`notifyBLECharacteristicValueChanged成功:${new Date().toString()}`);

                          count3--;
                          if (0 === count3) {
                            sendPassword({
                              deviceId, success: function () {
                                connectSuccess({deviceId});
                              }
                            });
                          }
                        },
                        fail: function (res) {
                          count3--;
                          fail();
                          console.log(`notifyBLECharacteristicValueChanged失败：${new Date().toString()},原因是${json2string(res)}`);
                        }
                      });
                    }

                  }, fail: function (res) {
                    count2--;
                    fail();
                    console.log(`getBLEDeviceCharacteristics失败：${new Date().toString()}，原因是:${json2string(res)}`);
                  }
                })
              }

            },
            fail: function (res) {
              count1--;
              fail();
              console.log(`getBLEDeviceServices失败：${new Date().toString()}，原因是:${json2string(res)}`);
            }
          });
        }


      },
      fail: function (res) {
        count0--;
        console.log(`createBLEConnection创建连接失败：${new Date().toString()}，原因是:${json2string(res)}`);
        fail();
      },
      complete: function () {
        complete();
      }
    });

  },

  setNameOfCube: function ({
                             deviceId, name, success = () => {
    }, fail = () => {
    }
                           }) {
    const {writeBLECharacteristicValue} = module.exports;
    writeBLECharacteristicValue({
      deviceId, value: [getSeqNum(), 0x34].concat(utf8arrayFixedLength(string2utf8array(name))), success: res => {
        log('设置名字成功');
        success();
      }, fail: () => {
        fail();
        // wx.showToast({
        //   title: '设置名字出错了',
        //   icon: 'none',
        //   mask: true
        // })
      }

    });
  },

  parseAdvertisData: function (advertisData) {
    const ad = ab2hex(advertisData);
    const productId = ad.substring(6, 10);//据此判断cube是否支持甲醛检测
    const serialNumber = ad.substring(0, 20); //序列号，唯一
    return {productId, serialNumber};
  },

  closeCube: function (callback = () => {
  }) {
    wx.setStorageSync('cubeIsDisconnecting', 1);
    // module.exports.cubeIsDisconnecting = true;
    const serialNumber = wx.getStorageSync('lastCubeSerialNumber') + '';
    let info = wx.getStorageSync(serialNumber), deviceId;
    try {
      info = 'string' === typeof info ? JSON.parse(info) : info;
      deviceId = info.deviceId;
    } catch (e) {
      deviceId = '';
    }
    if (deviceId) {
      //主动关闭连接时，不自动重连
      // app.globalData.autoConnect = 0; //使用storage。  app.js中会引用bluetooth，导致循环引用问题。
      const {closeBLEConnection} = module.exports;
      //不可发送通知，因为app引用了bluetooth，会导致循环引用
      const deviceInfoInstance = getPageInstance('deviceInfo');
      if (deviceInfoInstance) {
        deviceInfoInstance.setData({
          matchStatus: 4,
          isCharging: 0
        });

      }
      whenOfflineSaveInfo();
      console.log('开始调用断开蓝牙连接closeBLEConnection ')
      closeBLEConnection({
        deviceId, complete: function () {
          wx.setStorageSync('cubeIsDisconnecting', 0);
          console.log(`serialNumber:${serialNumber} 蓝牙连接已断开`);
          //设置cube为离线状态
          callback();
        }
      });
    } else {
      callback();
    }
  },
  lastCubeDeviceId: function () {
    let deviceId = null;
    try {
      const serialNumber = wx.getStorageSync('lastCubeSerialNumber') + '';
      let data = wx.getStorageSync(serialNumber + '') || {};
      data = 'string' === typeof data ? JSON.parse(data) : data;
      deviceId = data.deviceId;
    } catch (e) {
      deviceId = null;
    }
    return deviceId;
  },
  closeBLEConnection: function ({
                                  deviceId, success = () => {
    }, fail = () => {
    }, complete = () => {
    }
                                }) {
    if (deviceId) {
      wx.setStorageSync('autoReconnect', 0);
      wx.closeBLEConnection({
        deviceId, complete: function () {
          console.log(`wx.closeBLEConnection complete. autoReconnect=${wx.getStorageSync('autoReconnect')}`);
          complete();
        }, success, fail
      });
    }
  },
  specialData: function (valueJson) {
    const {timeStamp, pm25, hcho, battery, isCharging} = valueJson;
    return 0 === timeStamp && pm25 === 65535 && hcho === 65535 && battery === 0 && isCharging === 0;
  }
};